home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
PsL Monthly 1993 December
/
PSL Monthly Shareware CD-ROM (December 1993).iso
/
prgmming
/
dos
/
c
/
mpp.exe
/
MOUSE.DOC
< prev
next >
Wrap
Text File
|
1992-10-07
|
52KB
|
1,261 lines
Mouse++ Version 4.0
Copyright (c)1992 by Carl Moreland
10/06/92
-----------------------------------------------------------------------
Using the Mouse Class
To incorporate the mouse routines in your program, simply add
mouse.lib to your project or make file and #include mouse.h in any mo-
dule that calls a mouse function. mouse.lib contains all the functions
in mouse.cpp and cgc.cpp, but the functions are separated into differ-
ent object modules for greater efficiency. Note that mouse.lib is com-
piled for the large memory model.
An instance of the Mouse class (there can only be ONE instance) is
declared as extern in mouse.h, so any file that #includes mouse.h will
automatically have access to the mouse. You should NOT declare an in-
stance of the Mouse class in any part of your program. If you intend to
change the mouse cursor, then you also need to #include cursor.h.
When you link the mouse code into your program, an instance of the
mouse class is declared:
Mouse mouse;
The constructor Mouse::Mouse() calls the mouse driver reset function
(all mouse driver functions are called via interrupt 33h) and initia-
lizes the flags exists, enabled, and visible. exists is set to 1 if a
mouse was found and should be checked first. All other mouse class
functions check exists before issuing interrupt 33h calls and abort if
it is zero. enabled is initially zero meaning the mouse is disabled,
and visible is used by Show() and Hide() to keep track of the cursor
visibility. An example of initializing the mouse is:
#include "mouse.h"
main()
{
if(mouse.Exists()) // check for mouse
{
mouse.Enable(); // enable the mouse
mouse.Show(); // display the cursor
...
}
}
Again, including mouse.h automatically creates an instance of the
class, so all you have to do is start using it.
Once the mouse is initialized, it may be necessary to set some
parameters based on what video mode is being used. Strangely, the mouse
driver uses pixel coordinates for both text and graphics mode, with
(0,0) being the upper left hand corner of the screen, and (639,199)
being the default lower right hand corner. This would be correct for
CGA graphics mode and for normal 80x25 text mode - for text mode, this
means that each character cell is treated as an 8x8 pixel array. If you
are programming for the EGA or VGA as is the norm these days, you will
want to change the y-limit of 199 for high resolution graphics and 43
or 50 line text modes. Failure to do this means that the mouse cursor
will not move below the 200th line in graphics mode, or the 25th row in
text mode. (Older mouse drivers might not support more than 200 lines.
If this is the case, you will need to update your mouse driver.) For
640x480 VGA graphics, you need to set the y-limit to (0,479) by calling
yLimit(0,479). For 43 or 50 line text mode, the mouse driver still
treats each character cell as an 8x8 pixel array, so you need to set
the y-limit to (0,349) or (0,399), respectively. Since the default
width of 640 pixels is correct for most video modes, xLimit() is only
necessary when using SuperVGA graphics. (See the section on SuperVGA
support) Both xLimit() and yLimit() can also be used to limit the mouse
cursor to a small portion of the screen, such as a menu.
You may want to use a mouse cursor other than the default cursor.
To do this, call the function SetCursor() with the appropriate cursor
name. Many programs (especially graphics) will use several different
cursors depending on the location of the mouse (such as an arrow for
menus and an i-beam for text) or the particular function being pro-
cessed (such as an hourglass for wait). Several cursors are predefined
in the file cursor.h. To use them, simply include this header file in
whatever module changes the cursor. For more information on cursors,
see the Mouse Cursors section.
Finally, you may want to set the motion parameters, which include
the mickey-to-pixel ratio and the double-speed threshold. The mickey-
to-pixel ratio is set by MickToPix() and defines how many mickeys it
takes to move the mouse 8 pixels. (A mickey is single count of mouse
motion. Most mice are 200 "dots-per-inch", which means that one inch of
movement results in 200 mickeys.) If both the x and y parameters are
set to 8, then there will be a one-to-one correlation between mouse
motion and cursor motion. The default values are 8 in the horizontal
direction and 16 for the vertical. The vertical value of 16 means the
mouse must be moved twice as far vertically as horizontally to get the
same cursor movement. This is fine for text mode where the equivalent
screen resolution of 640x200 results in an equivalent pixel aspect
ratio of 2.4-to-1. In EGA/VGA graphics mode the y-direction will seem
noticeably slower, particularly for 640x480 which has an equivalent
pixel aspect ratio of 1-to-1. A vertical ratio of 8 will cure this.
The lower the ratio, the farther the cursor will move for a given mouse
movement. Setting either ratio lower than 8 means that the cursor can-
not be located on every pixel. For example, setting the ratio to 4 will
cause the cursor to move 2 pixels for every mickey. The double-speed
threshold is set by a call to SetSpeedThreshold(). When the speed of
the mouse (in mickeys per second) exceeds the speed parameter passed to
SetSpeedThreshold(), the motion speed of the cursor will double. A com-
plete initialization might look like this:
#include "mouse.h"
#include "cursor.h"
main()
{
{ initialize screen };
if(mouse.Exists())
{
mouse.SetCursor(cross);
mouse.yLimit(0,479); // VGA 640x480
mouse.MickToPix(8,8);
mouse.SetSpeedThreshold(32);
mouse.Enable();
mouse.Show();
...
}
}
The mouse should be reset before your program terminates so that
the calling program does not inherit any strange parameters. This is
particularly true of the event handler. Because it is an interrupt rou-
tine, failure to reset the mouse could lead to a system crash if the
handler is still pointing to the address of what used to be your hand-
ler routine. The destructor Mouse::~Mouse() first resets the mouse sta-
tus by calling function 00h, and then restores the original event hand-
ler with function 14h.
-----------------------------------------------------------------------
Reading the Mouse
Most of the standard mouse functions stuff any return values di-
rectly into the class variables and have a return type void. This is
because many mouse functions return more than one item of information.
You can then use the appropriate inline function to read the required
private variable. To check for the mouse position, for instance, you
would call Position() followed by either x() or y(), or both, such as:
for(;;)
{
mouse.Position();
if(mouse.x() > 320 || mouse.y() > 100)
do_something();
}
This method has the advantage of capturing both the x and y positions
with a single function call, and those variables can then be read at
your leisure. However, we generally don't care where the mouse is
located unless a button event that we are looking for has occurred.
Position() also returns the status of the mouse buttons, so we can also
check them:
for(;;)
{
mouse.Position();
if(mouse.LB_Dn()) // check for left button down
{
if(mouse.x() > 320 || mouse.y() > 100)
do_something();
}
else
do_something_else();
}
This loop will continuously check to see if the left button has been
pressed. If the do_something_else() code is slow then there is a pos-
sibility that a button press could be missed since Position() returns
the real-time status of the mouse. That is, during execution of the
do_somethin